package com.beta.cust.bind.datasync.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.beta.cat.service.RedissonService;
import com.beta.cust.bind.datasync.constant.BusinessConstant;
import com.beta.cust.bind.datasync.constant.CacheConstans;
import com.beta.cust.bind.datasync.dto.SelectReq;
import com.beta.cust.bind.datasync.dto.WeixinDepListDTO;
import com.beta.cust.bind.datasync.mapper.entity.AuthCorpInfo;
import com.beta.cust.bind.datasync.mapper.entity.DepartmentInfo;
import com.beta.cust.bind.datasync.mapper.entity.EmpDepRef;
import com.beta.cust.bind.datasync.service.IDepartmentInfoService;
import com.beta.cust.bind.datasync.service.IEmpDepRefService;
import com.beta.cust.bind.datasync.service.ISyncWechatDepartment;
import com.beta.cust.bind.datasync.service.IWechatWorkService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Auther: wangjiang
 * @Date: 2024/4/11 16:28
 * @Description:
 */
@Service
@Slf4j
public class SyncWechatWorkDepartmentImpl implements ISyncWechatDepartment {

    @Autowired
    private RedissonService redissonService;

    @Autowired
    private IWechatWorkService wechatWorkService;

    @Autowired
    private AuthCorpInfoServiceImpl corpInfoService;

    @Resource
    private IDepartmentInfoService departmentInfoService;

    @Autowired
    private IEmpDepRefService empDepRefService;

    /**
     * 同步企微端部门信息 本企业 和 下游企业获取token方式不一致 分开同步
     * 详情见：https://developer.work.weixin.qq.com/document/path/90208
     */
    @Override
    public void syncWechatWorkDepartment(String corpId) {
        String lockKey = String.format(CacheConstans.SYNC_DEP_INFO, corpId);
        try {
            if (redissonService.tryLock(lockKey, CacheConstans.WAIT_TIME)) {//一直锁到结束
                LocalDateTime excuteBatchTime = LocalDateTime.now();
                //1.同步本企业部门信息
                WeixinDepListDTO dto = wechatWorkService.departmentList(false, corpId, null);
                List<WeixinDepListDTO.DepartmentDetailDTO> detailDTOS = dto.getDepartment();
                //返回部门不为空时，保存至数据库
                if (!CollectionUtils.isEmpty(detailDTOS)) {
                    syncDepList(detailDTOS, corpId);
                }

                //2.循环下游企业添加部门信息
                SelectReq req = new SelectReq();
                req.setPageSize(10);
                while (true) {
                    //2.1、分页查询下游企业信息
                    IPage<AuthCorpInfo> corpPage = corpInfoService.selectPage(req);
                    List<AuthCorpInfo> corpInfos = corpPage.getRecords();
                    if (CollectionUtils.isEmpty(corpInfos)) {
                        break;
                    }
                    req.setId(corpInfos.get(corpInfos.size() - 1).getId());
                    //2.2 循环同步企业部门信息
                    for (AuthCorpInfo info : corpInfos) {
                        dto = wechatWorkService.departmentList(false, info.getCorpId(), info.getAgentId());
                        detailDTOS = dto.getDepartment();
                        //返回部门不为空时，保存至数据库
                        if (!CollectionUtils.isEmpty(detailDTOS)) {
                            syncDepList(detailDTOS, info.getCorpId());
                        }
                    }
                }

                //3.全部部门同步结束后，更改更新时间在任务启动之前的数据为软删除
                afterDeleteDepartment(excuteBatchTime);
            } else {
                log.warn("syncWechatWorkDepartment 当前已有定时任务运行中...");
            }
        } catch (Exception e) {
            log.error("syncWechatWorkDepartment error：{}", e.getMessage(), e);
        } finally {
            redissonService.unlock(lockKey);
        }
    }

    @Override
    public void createDepartMent(Long deptId, String corpId, String agentId) {
        log.info("部门回调-创建部门:{}", deptId);
        //1.查询数据库历史记录 是否存在该部门 不存在则新增 存在则修改
        Integer count = departmentInfoService.count(new LambdaQueryWrapper<DepartmentInfo>()
                .eq(DepartmentInfo::getCorpId, corpId)
                .eq(DepartmentInfo::getDepId, deptId));
        if (count > 0) {
            updateDepartment(deptId, corpId, agentId);
            return;
        }
        //2. 历史记录不存在 新增 调用企微接口 获取部门详细信息
        WeixinDepListDTO.DepartmentDetailDTO dtoInsert = wechatWorkService.departmentDetail(deptId, corpId, agentId);
        DepartmentInfo departmentInfo = new DepartmentInfo();
        departmentInfo.setCorpId(corpId);
        departmentInfo.setDepId(deptId);
        departmentInfo.setDepName(dtoInsert.getName());
        departmentInfo.setParentId(dtoInsert.getParentid());
        departmentInfo.setDepOrder(dtoInsert.getOrder());
        departmentInfo.setDelFlag(BusinessConstant.IS_NOT_DEL_FLAG);
        departmentInfoService.save(departmentInfo);
    }

    @Override
    public void updateDepartment(Long deptId, String corpId, String agentId) {
        log.info("部门回调-更新部门:{}", deptId);
        //调用企微接口 获取部门详细信息
        WeixinDepListDTO.DepartmentDetailDTO dtoUpdate = wechatWorkService.departmentDetail(deptId, corpId, agentId);
        DepartmentInfo departmentInfo = new DepartmentInfo();
        departmentInfo.setDepId(dtoUpdate.getId());
        departmentInfo.setDepName(dtoUpdate.getName());
        departmentInfo.setParentId(dtoUpdate.getParentid());
        departmentInfo.setDepOrder(dtoUpdate.getOrder());
        departmentInfo.setDelFlag(BusinessConstant.IS_NOT_DEL_FLAG);
        departmentInfo.setUpdateTime(Timestamp.valueOf(LocalDateTime.now()));
        departmentInfoService.update(departmentInfo, new LambdaQueryWrapper<DepartmentInfo>()
                .eq(DepartmentInfo::getCorpId, corpId)
                .eq(DepartmentInfo::getDepId, deptId));
    }

    @Override
    public void deleteDepartment(Long deptId, String corpId) {
        log.info("部门回调-删除部门:{}", deptId);
        //1.删除部门信息
        DepartmentInfo departmentInfo = new DepartmentInfo();
        departmentInfo.setDelFlag(BusinessConstant.IS_DEL_FLAG);
        departmentInfoService.update(departmentInfo, new LambdaQueryWrapper<DepartmentInfo>()
                .eq(DepartmentInfo::getCorpId, corpId)
                .eq(DepartmentInfo::getDepId, deptId));
        //2. 删除部门-成员关系
        EmpDepRef empDepRef = new EmpDepRef();
        empDepRef.setDelFlag(BusinessConstant.IS_DEL_FLAG);
        empDepRefService.update(empDepRef, new LambdaQueryWrapper<EmpDepRef>()
                .eq(EmpDepRef::getCorpId, corpId)
                .eq(EmpDepRef::getDepId, deptId));
    }


    private void syncDepList(List<WeixinDepListDTO.DepartmentDetailDTO> detailDTOS, String corpId) {
        //1.获取所有的depId集合
        Set<Long> depIdList = new HashSet<>();
        for (WeixinDepListDTO.DepartmentDetailDTO dto : detailDTOS) {
            depIdList.add(dto.getId());
        }
        //2.根据corpId,depId查询数据库
        List<DepartmentInfo> existList = departmentInfoService.list(new LambdaQueryWrapper<DepartmentInfo>().eq(DepartmentInfo::getCorpId, corpId)
                .in(DepartmentInfo::getDepId, depIdList));
        List<DepartmentInfo> addList = new ArrayList<>();
        List<DepartmentInfo> updateList = new ArrayList<>();
        //3.1数据库全部数据都不存在 则直接新增
        if (CollectionUtils.isEmpty(existList)) {
            addList = getDepList(detailDTOS, corpId);
        } else {
            List<Long> existDepIdList = existList.stream().map(DepartmentInfo::getDepId).collect(Collectors.toList());
            Map<Long, DepartmentInfo> depMap = existList.stream().collect(Collectors.toMap(DepartmentInfo::getDepId, a -> a, (a, b) -> a));
            //3.2数据库存在则新增 数据库不存在则新增
            for (WeixinDepListDTO.DepartmentDetailDTO dto : detailDTOS) {
                if (existDepIdList.contains(dto.getId())) {
                    updateList.add(getDep(dto, depMap.get(dto.getId()), corpId));
                } else {
                    DepartmentInfo departmentInfo = new DepartmentInfo();
                    addList.add(getDep(dto, departmentInfo, corpId));
                }
            }
        }
        if (!CollectionUtils.isEmpty(addList)) {
            departmentInfoService.saveBatch(addList);
        }
        if (!CollectionUtils.isEmpty(updateList)) {
            departmentInfoService.updateBatchById(updateList);
        }
    }

    private List<DepartmentInfo> getDepList(List<WeixinDepListDTO.DepartmentDetailDTO> detailDTOS, String corpId) {
        List<DepartmentInfo> departmentInfos = new ArrayList<>();
        for (WeixinDepListDTO.DepartmentDetailDTO dto : detailDTOS) {
            DepartmentInfo departmentInfo = new DepartmentInfo();
            departmentInfo = getDep(dto, departmentInfo, corpId);
            departmentInfos.add(departmentInfo);
        }
        return departmentInfos;
    }

    private DepartmentInfo getDep(WeixinDepListDTO.DepartmentDetailDTO dto, DepartmentInfo departmentInfo, String corpId) {
        departmentInfo.setCorpId(corpId);
        departmentInfo.setDepId(dto.getId());
        departmentInfo.setDepName(dto.getName());
        departmentInfo.setParentId(dto.getParentid());
        departmentInfo.setDepOrder(dto.getOrder());
        departmentInfo.setDelFlag(BusinessConstant.IS_NOT_DEL_FLAG);
        departmentInfo.setUpdateTime(Timestamp.valueOf(LocalDateTime.now()));
        return departmentInfo;
    }

    private void afterDeleteDepartment(LocalDateTime syncTime) {
        try {
            //避免数据太少 快速结束 误删除
            Thread.sleep(2000);
            DepartmentInfo departmentInfo = new DepartmentInfo();
            departmentInfo.setDelFlag(BusinessConstant.IS_DEL_FLAG);
            departmentInfoService.update(departmentInfo, new LambdaQueryWrapper<DepartmentInfo>().lt(DepartmentInfo::getUpdateTime, Timestamp.valueOf(syncTime)));
        } catch (Exception e) {
            log.error("afterDeleteCorp error:{}", e.getMessage(), e);
        }

    }
}
